package com.cehome.cloudbox.flowalbe;

import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.RepositoryServiceImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>类名: FlowableTaskService</p>
 * <p>描述:Flowable工作流任务相关接口</p>
 * <p>创建人: wangxj</p>
 * <p>创建时间: 2018/10/26 22:29</p>
 * <p>@version 2.0  </p>
 * <p>修改内容: ......</p>
 * <p>修改说明: ......</p>
 * <p>修改时间: ......</p>
 * <p>修改人: ......</p>
 * <p>每次修改，请增加上述修改信息说明</>
 */
@Service
public class FlowableTaskService {
    @Resource
    ProcessEngine processEngine;
    @Resource
    RepositoryService repositoryService;
    @Resource
    RuntimeService runtimeService;
    @Resource
    TaskService taskService;
    @Resource
    HistoryService historyService;
    @Autowired
    SpringProcessEngineConfiguration springProcessEngineConfiguration;



    public List<Task> startProcessInstByProcessDefinitionKey(String processDefinitionKey, Map<String,Object> map){
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey).latestVersion().singleResult();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,map);
        String processInstanceId = processInstance.getId();
        return taskService.createTaskQuery().processInstanceId(processInstanceId).list();
    }


    public List<HistoricTaskInstance> getHistoryTask(String processInstanceId){
        List<HistoricTaskInstance> taskInstances = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).processFinished().list();
        return taskInstances;
    }


    public List<Task> getTasksByUserId(String userId){
        //获取所在组别任务
        List<Task> groupTaskList=taskService.createTaskQuery().taskCandidateGroup(userId).list();
        //获取代理任务
        List<Task> assigneeTaskList=taskService.createTaskQuery().taskAssignee(userId).list();
        //获取用户任务
        List<Task> userTaskList=taskService.createTaskQuery().taskCandidateUser(userId).list();
        //排除重复的
        for(int i=0;i<assigneeTaskList.size();i++){
            if(!groupTaskList.contains(assigneeTaskList.get(i))){
                groupTaskList.add(assigneeTaskList.get(i));
            }
        }
        for(Task task:userTaskList){
            if(!groupTaskList.contains(task)){
                groupTaskList.add(task);
            }
        }
        return groupTaskList;
    }


    public List<Task> getTasksByAssignee(String userId){
        //获取代理任务
        return taskService.createTaskQuery().taskAssignee(userId).list();
    }


    public List<Task> getTasksByGroup(String userId){
        //获取组任务
        return taskService.createTaskQuery().taskCandidateGroup(userId).list();
    }


    public List<Task> getTasksByUser(String userId){
        //获取用户代办任务
        return taskService.createTaskQuery().taskCandidateUser(userId).list();
    }

    public List<Task> getTaskListByProcessInstanceId(String processInstanceId){
        return taskService.createTaskQuery().processInstanceId(processInstanceId).list();
    }


    public List<Task> getTaskListByprocessinstanchIdAndUserId(String processInstanceId, String userId){
        //获取所在组别任务
        List<Task> groupTaskList=taskService.createTaskQuery().processInstanceId(processInstanceId).taskCandidateGroup(userId).list();
        //获取代理任务
        List<Task> assigneeTaskList=taskService.createTaskQuery().processInstanceId(processInstanceId).taskAssignee(userId).list();
        //获取用户任务
        List<Task> userTaskList=taskService.createTaskQuery().processInstanceId(processInstanceId).taskCandidateUser(userId).list();
        //排除重复的
        for(int i=0;i<assigneeTaskList.size();i++){
            if(!groupTaskList.contains(assigneeTaskList.get(i))){
                groupTaskList.add(assigneeTaskList.get(i));
            }
        }
        for(Task task:userTaskList){
            if(!groupTaskList.contains(task)){
                groupTaskList.add(task);
            }
        }
        return groupTaskList;
    }


    public Task getTaskListByprocessinstanchIdAndUserId(String processInstanceId, String userId, String taskName){
        //获取所在组别任务
        List<Task> groupTaskList=taskService.createTaskQuery().processInstanceId(processInstanceId).taskCandidateGroup(userId).taskName(taskName).list();
        //获取代理任务
        List<Task> assigneeTaskList=taskService.createTaskQuery().processInstanceId(processInstanceId).taskAssignee(userId).taskName(taskName).list();
        //获取用户任务
        List<Task> userTaskList=taskService.createTaskQuery().processInstanceId(processInstanceId).taskCandidateUser(userId).taskName(taskName).list();
        //排除重复的
        for(int i=0;i<assigneeTaskList.size();i++){
            if(!groupTaskList.contains(assigneeTaskList.get(i))){
                groupTaskList.add(assigneeTaskList.get(i));
            }
        }
        for(Task task:userTaskList){
            if(!groupTaskList.contains(task)){
                groupTaskList.add(task);
            }
        }
        if(null!=groupTaskList){
            if(groupTaskList.size()==1){
                return groupTaskList.get(0);
            }
            if(groupTaskList.size()>1){
                throw new FlowableException(userId+"该用户同一流程实例下同一任务名称存在多个任务,请确定流程配置是否正确!");
            }
        }
        return null;
    }


    public List<Task> getTaskListByprocessDefIdAndUserId(String processDefId, String userId){
        //获取所在组别任务
        List<Task> groupTaskList=taskService.createTaskQuery().processDefinitionId(processDefId).taskCandidateGroup(userId).list();
        //获取代理任务
        List<Task> assigneeTaskList=taskService.createTaskQuery().processDefinitionId(processDefId).taskAssignee(userId).list();
        //获取用户任务
        List<Task> userTaskList=taskService.createTaskQuery().processDefinitionId(processDefId).taskCandidateUser(userId).list();
        //排除重复的
        for(int i=0;i<assigneeTaskList.size();i++){
            if(!groupTaskList.contains(assigneeTaskList.get(i))){
                groupTaskList.add(assigneeTaskList.get(i));
            }
        }
        for(Task task:userTaskList){
            if(!groupTaskList.contains(task)){
                groupTaskList.add(task);
            }
        }
        return groupTaskList;
    }


    public List<Task> getTaskListByprocessDefIdAndUserId(String processDefId, String userId, String taskName){
        //获取所在组别任务
        List<Task> groupTaskList=taskService.createTaskQuery().processDefinitionId(processDefId).taskName(taskName).taskCandidateGroup(userId).list();
        //获取代理任务
        List<Task> assigneeTaskList=taskService.createTaskQuery().processDefinitionId(processDefId).taskName(taskName).taskAssignee(userId).list();
        //获取用户任务
        List<Task> userTaskList=taskService.createTaskQuery().processDefinitionId(processDefId).taskName(taskName).taskCandidateUser(userId).list();
        //排除重复的
        for(int i=0;i<assigneeTaskList.size();i++){
            if(!groupTaskList.contains(assigneeTaskList.get(i))){
                groupTaskList.add(assigneeTaskList.get(i));
            }
        }
        for(Task task:userTaskList){
            if(!groupTaskList.contains(task)){
                groupTaskList.add(task);
            }
        }
        return groupTaskList;
    }


    public List<Task> getUserTaskListByprocessDefIdAndUserId(String processDefId, String userId){
        //获取用户任务
        List<Task> userTaskList=taskService.createTaskQuery().processDefinitionId(processDefId).taskCandidateUser(userId).list();
        return userTaskList;
    }

    public List<Task> getTasksByProcessInstanceIdAndTaskName(String processInstanceId, String taskName){
        //获取用户任务
        List<Task> userTaskList=taskService.createTaskQuery().taskName(taskName).processInstanceId(processInstanceId).list();
        return userTaskList;
    }


    public Task getTaskByProcessInstanceId(String processInstanceId){
        return taskService.createTaskQuery().processInstanceId(processInstanceId).active().singleResult();
    }

    public Task getTaskByProcessInstanceIdAndTaskName(String processInstanceId, String taskName){
        return taskService.createTaskQuery().taskName(taskName).processInstanceId(processInstanceId).active().singleResult();
    }


    public Task getTaskByProcessInstanceId(String processInstanceId, String taskkey){
        return taskService.createTaskQuery().processInstanceId(processInstanceId).active().taskDefinitionKey(taskkey).singleResult();
    }


    public List<Task> getActiveTasksByProcessInstanceId(String processInstanceId){
        return taskService.createTaskQuery().processInstanceId(processInstanceId).active().list();
    }

    public Task getTasksByProcessInstanceId(String executionId){
        return taskService.createTaskQuery().executionId(executionId).singleResult();
    }


    public Task getTaskByTaskId(String taskId) {
        //得到当前的任务
        Task task = this.processEngine.getTaskService()
                .createTaskQuery()
                .taskId(taskId)
                .singleResult();
        return task;
    }


    public void finishCurrentTaskByTaskId(String taskId){
        this.processEngine.getTaskService().complete(taskId);
    }


    public void finishCurrentTaskByTaskId(String taskId , Map<String , Object> map){
        this.processEngine.getTaskService().complete(taskId , map);
    }


    public void finishCurrentTaskByTaskId(Task task , Map<String , Object> map){
        String taskId=task.getId();
        this.processEngine.getTaskService().complete(taskId , map);
    }


    public void finishCurrentTaskByTaskId(Task task){
        String taskId=task.getId();
        this.processEngine.getTaskService().complete(taskId);
    }


    public FlowElement getNodeByTask(Task task,String node){
        ExecutionEntity ee = (ExecutionEntity)this.processEngine.getRuntimeService().createExecutionQuery()
                .executionId(task.getExecutionId()).singleResult();
        // 当前审批节点id
        String crruentActivityId = ee.getActivityId();
        //根据流程定义id获取流程实例对象
        BpmnModel bpmnModel = this.processEngine.getRepositoryService().getBpmnModel(task.getProcessDefinitionId());
        //根据活动节点id获取对应的node
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(crruentActivityId);
        //获取连接线
        List<SequenceFlow> outFlows = flowNode.getOutgoingFlows();
        for (SequenceFlow sequenceFlow : outFlows) {
            //当前审批节点
            if ("now".equals(node)) {
                FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
                return sourceFlowElement;
            } else if ("next".equals(node)) {
                // 下一个审批节点
                FlowElement targetFlow = sequenceFlow.getTargetFlowElement();
                return targetFlow;
                /*if (targetFlow instanceof UserTask) {
                    System.out.println("下一节点: id=" + targetFlow.getId() + ",name=" + targetFlow.getName());
                }
                // 如果下个审批节点为结束节点
                if (targetFlow instanceof EndEvent) {
                    System.out.println("下一节点为结束节点：id=" + targetFlow.getId() + ",name=" + targetFlow.getName());
                }*/
            }
        }
        return null;
    }

    public InputStream getProccessActivitiPathImage(String processInstanceId) {
        InputStream inputStream=null;
        //  获取历史流程实例
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        if (null!=historicProcessInstance){
            // 获取流程定义
            ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                    .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());
            // 获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序
            List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstanceId).orderByHistoricActivityInstanceId().asc().list();
            // 已执行的节点ID集合
            List<String> executedActivityIdList = new ArrayList<String>();
            int index = 1;
            //logger.info("获取已经执行的节点ID");
            for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
                executedActivityIdList.add(activityInstance.getActivityId());
                index++;
            }
            BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
            // 已执行的线集合
            List<String> flowIds = new ArrayList<String>();
            // 获取流程走过的线 (getHighLightedFlows是下面的方法)
            flowIds = getHighLightedFlows(bpmnModel,processDefinition, historicActivityInstanceList);
            // 获取流程图图像字符流
            ProcessDiagramGenerator diagramGenerator = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
            //配置字体
            ProcessEngineConfiguration engConf = springProcessEngineConfiguration;
            inputStream = diagramGenerator.generateDiagram(bpmnModel, "JPG", executedActivityIdList,flowIds,engConf.getActivityFontName()
                    , engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(), 1.0, true);

        }
        return inputStream;
    }

    public List<String> getHighLightedFlows(BpmnModel bpmnModel,ProcessDefinitionEntity processDefinitionEntity,List<HistoricActivityInstance> historicActivityInstances) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //24小时制
        List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId
        for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
            // 对历史流程节点进行遍历
            // 得到节点定义的详细信息
            FlowElement nowFlow = bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId());
            if(nowFlow instanceof SequenceFlow){
                continue;
            }
            FlowNode  activityImpl = (FlowNode) nowFlow;
            List<FlowElement> sameStartTimeNodes = new ArrayList<FlowElement>();// 用以保存后续开始时间相同的节点
            FlowElement sameActivityImpl1 = null;
            // 第一个节点
            HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i);
            HistoricActivityInstance activityImp2_ ;
            for(int k = i + 1 ; k <= historicActivityInstances.size() - 1; k++) {
                activityImp2_ = historicActivityInstances.get(k);// 后续第1个节点
                if ( activityImpl_.getActivityType().equals("userTask") && activityImp2_.getActivityType().equals("userTask") &&
                        df.format(activityImpl_.getStartTime()).equals(df.format(activityImp2_.getStartTime()))) {
                    //都是usertask，且主节点与后续节点的开始时间相同，说明不是真实的后继节点
                } else {
                    sameActivityImpl1 = bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId());//找到紧跟在后面的一个节点
                    break;
                }
            }
            sameStartTimeNodes.add(sameActivityImpl1); // 将后面第一个节点放在时间相同节点的集合里
            for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
                HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点
                HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点
                if (df.format(activityImpl1.getStartTime()).equals(df.format(activityImpl2.getStartTime()))  ) {
                    // 如果第一个节点和第二个节点开始时间相同保存
                    FlowElement sameActivityImpl2 = bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId());
                    sameStartTimeNodes.add(sameActivityImpl2);
                } else {
                    // 有不相同跳出循环
                    break;
                }
            }
            FlowNode flowNode;
            List<SequenceFlow> pvmTransitions = activityImpl.getOutgoingFlows() ; // 取出节点的所有出去的线
            for (SequenceFlow pvmTransition : pvmTransitions) {
                // 对所有的线进行遍历
                FlowElement pvmActivityImpl = bpmnModel.getMainProcess().getFlowElement( pvmTransition.getTargetRef());// 如果取出的线的目标节点存在时间相同的节点里，保存该线的id，进行高亮显示
                if (sameStartTimeNodes.contains(pvmActivityImpl)) {
                    highFlows.add(pvmTransition.getId());
                }
            }
        }
        return highFlows;

    }
}
